home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / libogg / libvorbis-1.0rc3 / vq / bookutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-27  |  19.9 KB  |  739 lines

  1. /********************************************************************
  2.  *                                                                  *
  3.  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
  4.  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
  5.  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6.  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  7.  *                                                                  *
  8.  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
  9.  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  10.  *                                                                  *
  11.  ********************************************************************
  12.  
  13.  function: utility functions for loading .vqh and .vqd files
  14.  last mod: $Id: bookutil.c,v 1.26 2001/12/20 01:00:39 segher Exp $
  15.  
  16.  ********************************************************************/
  17.  
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <math.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include "bookutil.h"
  24.  
  25. /* A few little utils for reading files */
  26. /* read a line.  Use global, persistent buffering */
  27. static char *linebuffer=NULL;
  28. static int  lbufsize=0;
  29. char *get_line(FILE *in){
  30.   long sofar=0;
  31.   if(feof(in))return NULL;
  32.  
  33.   while(1){
  34.     int gotline=0;
  35.  
  36.     while(!gotline){
  37.       if(sofar+1>=lbufsize){
  38.         if(!lbufsize){  
  39.           lbufsize=1024;
  40.           linebuffer=_ogg_malloc(lbufsize);
  41.         }else{
  42.           lbufsize*=2;
  43.           linebuffer=_ogg_realloc(linebuffer,lbufsize);
  44.         }
  45.       }
  46.       {
  47.         long c=fgetc(in);
  48.         switch(c){
  49.         case EOF:
  50.       if(sofar==0)return(NULL);
  51.       /* fallthrough correct */
  52.         case '\n':
  53.           linebuffer[sofar]='\0';
  54.           gotline=1;
  55.           break;
  56.         default:
  57.           linebuffer[sofar++]=c;
  58.           linebuffer[sofar]='\0';
  59.           break;
  60.         }
  61.       }
  62.     }
  63.     
  64.     if(linebuffer[0]=='#'){
  65.       sofar=0;
  66.     }else{
  67.       return(linebuffer);
  68.     }
  69.   }
  70. }
  71.  
  72. /* read the next numerical value from the given file */
  73. static char *value_line_buff=NULL;
  74.  
  75. int get_line_value(FILE *in,float *value){
  76.   char *next;
  77.  
  78.   if(!value_line_buff)return(-1);
  79.  
  80.   *value=strtod(value_line_buff, &next);
  81.   if(next==value_line_buff){
  82.     value_line_buff=NULL;
  83.     return(-1);
  84.   }else{
  85.     value_line_buff=next;
  86.     while(*value_line_buff>44)value_line_buff++;
  87.     if(*value_line_buff==44)value_line_buff++;
  88.     return(0);
  89.   }
  90. }
  91.  
  92. int get_next_value(FILE *in,float *value){
  93.   while(1){
  94.     if(get_line_value(in,value)){
  95.       value_line_buff=get_line(in);
  96.       if(!value_line_buff)return(-1);
  97.     }else{
  98.       return(0);
  99.     }
  100.   }
  101. }
  102.  
  103. int get_next_ivalue(FILE *in,long *ivalue){
  104.   float value;
  105.   int ret=get_next_value(in,&value);
  106.   *ivalue=value;
  107.   return(ret);
  108. }
  109.  
  110. static float sequence_base=0.f;
  111. static int v_sofar=0;
  112. void reset_next_value(void){
  113.   value_line_buff=NULL;
  114.   sequence_base=0.f;
  115.   v_sofar=0;
  116. }
  117.  
  118. char *setup_line(FILE *in){
  119.   reset_next_value();
  120.   value_line_buff=get_line(in);
  121.   return(value_line_buff);
  122. }
  123.  
  124.  
  125. int get_vector(codebook *b,FILE *in,int start, int n,float *a){
  126.   int i;
  127.   const static_codebook *c=b->c;
  128.  
  129.   while(1){
  130.  
  131.     if(v_sofar==n || get_line_value(in,a)){
  132.       reset_next_value();
  133.       if(get_next_value(in,a))
  134.     break;
  135.       for(i=0;i<start;i++){
  136.     sequence_base=*a;
  137.     get_line_value(in,a);
  138.       }
  139.     }
  140.  
  141.     for(i=1;i<c->dim;i++)
  142.       if(get_line_value(in,a+i))
  143.     break;
  144.     
  145.     if(i==c->dim){
  146.       float temp=a[c->dim-1];
  147.       for(i=0;i<c->dim;i++)a[i]-=sequence_base;
  148.       if(c->q_sequencep)sequence_base=temp;
  149.       v_sofar++;
  150.       return(0);
  151.     }
  152.     sequence_base=0.f;
  153.   }
  154.  
  155.   return(-1);
  156. }
  157.  
  158. /* read lines fromt he beginning until we find one containing the
  159.    specified string */
  160. char *find_seek_to(FILE *in,char *s){
  161.   rewind(in);
  162.   while(1){
  163.     char *line=get_line(in);
  164.     if(line){
  165.       if(strstr(line,s))
  166.     return(line);
  167.     }else
  168.       return(NULL);
  169.   }
  170. }
  171.  
  172.  
  173. /* this reads the format as written by vqbuild/latticebuild; innocent
  174.    (legal) tweaking of the file that would not affect its valid
  175.    header-ness will break this routine */
  176.  
  177. codebook *codebook_load(char *filename){
  178.   codebook *b=_ogg_calloc(1,sizeof(codebook));
  179.   static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook)));
  180.   encode_aux_nearestmatch *a=NULL;
  181.   encode_aux_threshmatch *t=NULL;
  182.   encode_aux_pigeonhole *p=NULL;
  183.   int quant_to_read=0;
  184.   FILE *in=fopen(filename,"r");
  185.   char *line;
  186.   long i;
  187.  
  188.   if(in==NULL){
  189.     fprintf(stderr,"Couldn't open codebook %s\n",filename);
  190.     exit(1);
  191.   }
  192.  
  193.   /* find the codebook struct */
  194.   find_seek_to(in,"static static_codebook ");
  195.  
  196.   /* get the major important values */
  197.   line=get_line(in);
  198.   if(sscanf(line,"%ld, %ld,",
  199.         &(c->dim),&(c->entries))!=2){
  200.     fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
  201.     exit(1);
  202.   }
  203.   line=get_line(in);
  204.   line=get_line(in);
  205.   if(sscanf(line,"%d, %ld, %ld, %d, %d,",
  206.         &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant),
  207.         &(c->q_sequencep))!=5){
  208.     fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
  209.     exit(1);
  210.   }
  211.   
  212.   /* find the auxiliary encode struct[s] (if any) */
  213.   if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){
  214.     /* how big? */
  215.     c->nearest_tree=a=_ogg_calloc(1,sizeof(encode_aux_nearestmatch));
  216.     line=get_line(in);
  217.     line=get_line(in);
  218.     line=get_line(in);
  219.     line=get_line(in);
  220.     line=get_line(in);
  221.     if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){
  222.       fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line);
  223.       exit(1);
  224.     }
  225.  
  226.     /* load ptr0 */
  227.     find_seek_to(in,"static long _vq_ptr0");
  228.     reset_next_value();
  229.     a->ptr0=_ogg_malloc(sizeof(long)*a->aux);
  230.     for(i=0;i<a->aux;i++)
  231.       if(get_next_ivalue(in,a->ptr0+i)){
  232.     fprintf(stderr,"out of data while reading codebook %s\n",filename);
  233.     exit(1);
  234.       }
  235.     
  236.     /* load ptr1 */
  237.     find_seek_to(in,"static long _vq_ptr1");
  238.     reset_next_value();
  239.     a->ptr1=_ogg_malloc(sizeof(long)*a->aux);
  240.     for(i=0;i<a->aux;i++)
  241.       if(get_next_ivalue(in,a->ptr1+i)){
  242.     fprintf(stderr,"out of data while reading codebook %s\n",filename);
  243.     exit(1);
  244.     }
  245.     
  246.     
  247.     /* load p */
  248.     find_seek_to(in,"static long _vq_p_");
  249.     reset_next_value();
  250.     a->p=_ogg_malloc(sizeof(long)*a->aux);
  251.     for(i=0;i<a->aux;i++)
  252.       if(get_next_ivalue(in,a->p+i)){
  253.     fprintf(stderr,"out of data while reading codebook %s\n",filename);
  254.     exit(1);
  255.       }
  256.     
  257.     /* load q */
  258.     find_seek_to(in,"static long _vq_q_");
  259.     reset_next_value();
  260.     a->q=_ogg_malloc(sizeof(long)*a->aux);
  261.     for(i=0;i<a->aux;i++)
  262.       if(get_next_ivalue(in,a->q+i)){
  263.     fprintf(stderr,"out of data while reading codebook %s\n",filename);
  264.     exit(1);
  265.       }    
  266.   }
  267.   
  268.   if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){
  269.     /* how big? */
  270.     c->thresh_tree=t=_ogg_calloc(1,sizeof(encode_aux_threshmatch));
  271.     line=get_line(in);
  272.     line=get_line(in);
  273.     line=get_line(in);
  274.     if(sscanf(line,"%d",&(t->quantvals))!=1){
  275.       fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line);
  276.       exit(1);
  277.     }
  278.     line=get_line(in);
  279.     if(sscanf(line,"%d",&(t->threshvals))!=1){
  280.       fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line);
  281.       exit(1);
  282.     }
  283.     /* load quantthresh */
  284.     find_seek_to(in,"static float _vq_quantthresh_");
  285.     reset_next_value();
  286.     t->quantthresh=_ogg_malloc(sizeof(float)*t->threshvals);
  287.     for(i=0;i<t->threshvals-1;i++)
  288.       if(get_next_value(in,t->quantthresh+i)){
  289.     fprintf(stderr,"out of data 1 while reading codebook %s\n",filename);
  290.     exit(1);
  291.       }    
  292.     /* load quantmap */
  293.     find_seek_to(in,"static long _vq_quantmap_");
  294.     reset_next_value();
  295.     t->quantmap=_ogg_malloc(sizeof(long)*t->threshvals);
  296.     for(i=0;i<t->threshvals;i++)
  297.       if(get_next_ivalue(in,t->quantmap+i)){
  298.     fprintf(stderr,"out of data 2 while reading codebook %s\n",filename);
  299.     exit(1);
  300.       }    
  301.   }
  302.     
  303.   if(find_seek_to(in,"static encode_aux_pigeonhole _vq_aux")){
  304.     int pigeons=1,i;
  305.     /* how big? */
  306.     c->pigeon_tree=p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole));
  307.     line=get_line(in);
  308.     if(sscanf(line,"%f, %f, %d, %d",&(p->min),&(p->del),
  309.           &(p->mapentries),&(p->quantvals))!=4){
  310.       fprintf(stderr,"5: syntax in %s in line:\t %s",filename,line);
  311.       exit(1);
  312.     }
  313.     line=get_line(in);
  314.     line=get_line(in);
  315.     if(sscanf(line,"%ld",&(p->fittotal))!=1){
  316.       fprintf(stderr,"6: syntax in %s in line:\t %s",filename,line);
  317.       exit(1);
  318.     }
  319.     /* load pigeonmap */
  320.     find_seek_to(in,"static long _vq_pigeonmap_");
  321.     reset_next_value();
  322.     p->pigeonmap=_ogg_malloc(sizeof(long)*p->mapentries);
  323.     for(i=0;i<p->mapentries;i++)
  324.       if(get_next_ivalue(in,p->pigeonmap+i)){
  325.     fprintf(stderr,"out of data (pigeonmap) while reading codebook %s\n",filename);
  326.     exit(1);
  327.       }    
  328.     /* load fitlist */
  329.     find_seek_to(in,"static long _vq_fitlist_");
  330.     reset_next_value();
  331.     p->fitlist=_ogg_malloc(sizeof(long)*p->fittotal);
  332.     for(i=0;i<p->fittotal;i++)
  333.       if(get_next_ivalue(in,p->fitlist+i)){
  334.     fprintf(stderr,"out of data (fitlist) while reading codebook %s\n",filename);
  335.     exit(1);
  336.       }    
  337.     /* load fitmap */
  338.     find_seek_to(in,"static long _vq_fitmap_");
  339.     reset_next_value();
  340.     for(i=0;i<c->dim;i++)pigeons*=p->quantvals;
  341.     p->fitmap=_ogg_malloc(sizeof(long)*pigeons);
  342.     for(i=0;i<pigeons;i++)
  343.       if(get_next_ivalue(in,p->fitmap+i)){
  344.     fprintf(stderr,"out of data (fitmap) while reading codebook %s\n",filename);
  345.     exit(1);
  346.       }    
  347.  
  348.     /* load fitlength */
  349.     find_seek_to(in,"static long _vq_fitlength_");
  350.     reset_next_value();
  351.     p->fitlength=_ogg_malloc(sizeof(long)*pigeons);
  352.     for(i=0;i<pigeons;i++)
  353.       if(get_next_ivalue(in,p->fitlength+i)){
  354.     fprintf(stderr,"out of data (fitlength) while reading codebook %s\n",filename);
  355.     exit(1);
  356.       }    
  357.   }
  358.  
  359.   switch(c->maptype){
  360.   case 0:
  361.     quant_to_read=0;
  362.     break;
  363.   case 1:
  364.     quant_to_read=_book_maptype1_quantvals(c);
  365.     break;
  366.   case 2:
  367.     quant_to_read=c->entries*c->dim;
  368.     break;
  369.   }
  370.     
  371.   /* load the quantized entries */
  372.   find_seek_to(in,"static long _vq_quantlist_");
  373.   reset_next_value();
  374.   c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read);
  375.   for(i=0;i<quant_to_read;i++)
  376.     if(get_next_ivalue(in,c->quantlist+i)){
  377.       fprintf(stderr,"out of data while reading codebook %s\n",filename);
  378.       exit(1);
  379.     }
  380.   
  381.   /* load the lengthlist */
  382.   find_seek_to(in,"_lengthlist");
  383.   reset_next_value();
  384.   c->lengthlist=_ogg_malloc(sizeof(long)*c->entries);
  385.   for(i=0;i<c->entries;i++)
  386.     if(get_next_ivalue(in,c->lengthlist+i)){
  387.       fprintf(stderr,"out of data while reading codebook %s\n",filename);
  388.       exit(1);
  389.     }
  390.  
  391.   /* got it all */
  392.   fclose(in);
  393.   
  394.   vorbis_book_init_encode(b,c);
  395.  
  396.   return(b);
  397. }
  398.  
  399. void spinnit(char *s,int n){
  400.   static int p=0;
  401.   static long lasttime=0;
  402.   long test;
  403.   struct timeval thistime;
  404.  
  405.   gettimeofday(&thistime,NULL);
  406.   test=thistime.tv_sec*10+thistime.tv_usec/100000;
  407.   if(lasttime!=test){
  408.     lasttime=test;
  409.  
  410.     fprintf(stderr,"%s%d ",s,n);
  411.  
  412.     p++;if(p>3)p=0;
  413.     switch(p){
  414.     case 0:
  415.       fprintf(stderr,"|    \r");
  416.       break;
  417.     case 1:
  418.       fprintf(stderr,"/    \r");
  419.       break;
  420.     case 2:
  421.       fprintf(stderr,"-    \r");
  422.       break;
  423.     case 3:
  424.       fprintf(stderr,"\\    \r");
  425.       break;
  426.     }
  427.     fflush(stderr);
  428.   }
  429. }
  430.  
  431. void build_tree_from_lengths(int vals, long *hist, long *lengths){
  432.   int i,j;
  433.   long *membership=_ogg_malloc(vals*sizeof(long));
  434.   long *histsave=alloca(vals*sizeof(long));
  435.   memcpy(histsave,hist,vals*sizeof(long));
  436.  
  437.   for(i=0;i<vals;i++)membership[i]=i;
  438.  
  439.   /* find codeword lengths */
  440.   /* much more elegant means exist.  Brute force n^2, minimum thought */
  441.   for(i=vals;i>1;i--){
  442.     int first=-1,second=-1;
  443.     long least=-1;
  444.     
  445.     spinnit("building... ",i);
  446.     
  447.     /* find the two nodes to join */
  448.     for(j=0;j<vals;j++)
  449.       if(least==-1 || hist[j]<least){
  450.     least=hist[j];
  451.     first=membership[j];
  452.       }
  453.     least=-1;
  454.     for(j=0;j<vals;j++)
  455.       if((least==-1 || hist[j]<least) && membership[j]!=first){
  456.     least=hist[j];
  457.     second=membership[j];
  458.       }
  459.     if(first==-1 || second==-1){
  460.       fprintf(stderr,"huffman fault; no free branch\n");
  461.       exit(1);
  462.     }
  463.     
  464.     /* join them */
  465.     least=hist[first]+hist[second];
  466.     for(j=0;j<vals;j++)
  467.       if(membership[j]==first || membership[j]==second){
  468.     membership[j]=first;
  469.     hist[j]=least;
  470.     lengths[j]++;
  471.       }
  472.   }
  473.   for(i=0;i<vals-1;i++)
  474.     if(membership[i]!=membership[i+1]){
  475.       fprintf(stderr,"huffman fault; failed to build single tree\n");
  476.       exit(1);
  477.     }
  478.  
  479.   /* for sanity check purposes: how many bits would it have taken to
  480.      encode the training set? */
  481.   {
  482.     long bitsum=0;
  483.     long samples=0;
  484.     for(i=0;i<vals;i++){
  485.       bitsum+=(histsave[i]-1)*lengths[i];
  486.       samples+=histsave[i]-1;
  487.     }
  488.  
  489.     if(samples){
  490.       fprintf(stderr,"\rTotal samples in training set: %ld      \n",samples);
  491.       fprintf(stderr,"\rTotal bits used to represent training set: %ld\n",
  492.           bitsum);
  493.     }
  494.   }
  495.  
  496.   free(membership);
  497. }
  498.  
  499. /* wrap build_tree_from_lengths to allow zero entries in the histogram */
  500. void build_tree_from_lengths0(int vals, long *hist, long *lengths){
  501.  
  502.   /* pack the 'sparse' hit list into a dense list, then unpack
  503.      the lengths after the build */
  504.  
  505.   int upper=0,i;
  506.   long *lengthlist=_ogg_calloc(vals,sizeof(long));
  507.   long *newhist=alloca(vals*sizeof(long));
  508.  
  509.   for(i=0;i<vals;i++)
  510.     if(hist[i]>0)
  511.       newhist[upper++]=hist[i];
  512.  
  513.   if(upper != vals){
  514.     fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n",
  515.         vals-upper,upper);
  516.   }
  517.     
  518.   build_tree_from_lengths(upper,newhist,lengthlist);
  519.       
  520.   upper=0;
  521.   for(i=0;i<vals;i++)
  522.     if(hist[i]>0)
  523.       lengths[i]=lengthlist[upper++];
  524.     else
  525.       lengths[i]=0;
  526.  
  527.   free(lengthlist);
  528. }
  529.  
  530. void write_codebook(FILE *out,char *name,const static_codebook *c){
  531.   encode_aux_pigeonhole *p=c->pigeon_tree;
  532.   encode_aux_threshmatch *t=c->thresh_tree;
  533.   encode_aux_nearestmatch *n=c->nearest_tree;
  534.   int i,j,k;
  535.  
  536.   /* save the book in C header form */
  537.   fprintf(out,
  538.   "/********************************************************************\n"
  539.   " *                                                                  *\n"
  540.   " * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *\n"
  541.   " * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *\n"
  542.   " * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *\n"
  543.   " * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *\n"
  544.   " *                                                                  *\n"
  545.   " * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *\n"
  546.   " * by the XIPHOPHORUS Company http://www.xiph.org/                  *\n"
  547.   " *                                                                  *\n"
  548.   " ********************************************************************\n"
  549.   "\n"
  550.   " function: static codebook autogenerated by vq/somethingorother\n"
  551.   "\n"
  552.   " ********************************************************************/\n\n");
  553.  
  554.   fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
  555.   fprintf(out,"#include \"codebook.h\"\n\n");
  556.  
  557.   /* first, the static vectors, then the book structure to tie it together. */
  558.   /* quantlist */
  559.   if(c->quantlist){
  560.     long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim);
  561.     fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
  562.     for(j=0;j<vals;j++){
  563.       fprintf(out,"\t%ld,\n",c->quantlist[j]);
  564.     }
  565.     fprintf(out,"};\n\n");
  566.   }
  567.  
  568.   /* lengthlist */
  569.   fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
  570.   for(j=0;j<c->entries;){
  571.     fprintf(out,"\t");
  572.     for(k=0;k<16 && j<c->entries;k++,j++)
  573.       fprintf(out,"%2ld,",c->lengthlist[j]);
  574.     fprintf(out,"\n");
  575.   }
  576.   fprintf(out,"};\n\n");
  577.  
  578.   if(t){
  579.     /* quantthresh */
  580.     fprintf(out,"static float _vq_quantthresh_%s[] = {\n",name);
  581.     for(j=0;j<t->threshvals-1;){
  582.       fprintf(out,"\t");
  583.       for(k=0;k<8 && j<t->threshvals-1;k++,j++)
  584.     fprintf(out,"%.5g, ",t->quantthresh[j]);
  585.       fprintf(out,"\n");
  586.     }
  587.     fprintf(out,"};\n\n");
  588.  
  589.     /* quantmap */
  590.     fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
  591.     for(j=0;j<t->threshvals;){
  592.       fprintf(out,"\t");
  593.       for(k=0;k<8 && j<t->threshvals;k++,j++)
  594.     fprintf(out,"%5ld,",t->quantmap[j]);
  595.       fprintf(out,"\n");
  596.     }
  597.     fprintf(out,"};\n\n");  
  598.  
  599.     fprintf(out,"static encode_aux_threshmatch _vq_auxt_%s = {\n",name);
  600.     fprintf(out,"\t_vq_quantthresh_%s,\n",name);
  601.     fprintf(out,"\t_vq_quantmap_%s,\n",name);
  602.     fprintf(out,"\t%d,\n",t->quantvals);
  603.     fprintf(out,"\t%d\n};\n\n",t->threshvals);
  604.   }
  605.  
  606.   if(p){
  607.     int pigeons=1;
  608.     for(i=0;i<c->dim;i++)pigeons*=p->quantvals;
  609.  
  610.     /* pigeonmap */
  611.     fprintf(out,"static long _vq_pigeonmap_%s[] = {\n",name);
  612.     for(j=0;j<p->mapentries;){
  613.       fprintf(out,"\t");
  614.       for(k=0;k<8 && j<p->mapentries;k++,j++)
  615.     fprintf(out,"%5ld, ",p->pigeonmap[j]);
  616.       fprintf(out,"\n");
  617.     }
  618.     fprintf(out,"};\n\n");
  619.     /* fitlist */
  620.     fprintf(out,"static long _vq_fitlist_%s[] = {\n",name);
  621.     for(j=0;j<p->fittotal;){
  622.       fprintf(out,"\t");
  623.       for(k=0;k<8 && j<p->fittotal;k++,j++)
  624.     fprintf(out,"%5ld, ",p->fitlist[j]);
  625.       fprintf(out,"\n");
  626.     }
  627.     fprintf(out,"};\n\n");
  628.     /* fitmap */
  629.     fprintf(out,"static long _vq_fitmap_%s[] = {\n",name);
  630.     for(j=0;j<pigeons;){
  631.       fprintf(out,"\t");
  632.       for(k=0;k<8 && j<pigeons;k++,j++)
  633.     fprintf(out,"%5ld, ",p->fitmap[j]);
  634.       fprintf(out,"\n");
  635.     }
  636.     fprintf(out,"};\n\n");
  637.     /* fitlength */
  638.     fprintf(out,"static long _vq_fitlength_%s[] = {\n",name);
  639.     for(j=0;j<pigeons;){
  640.       fprintf(out,"\t");
  641.       for(k=0;k<8 && j<pigeons;k++,j++)
  642.     fprintf(out,"%5ld, ",p->fitlength[j]);
  643.       fprintf(out,"\n");
  644.     }
  645.     fprintf(out,"};\n\n");
  646.  
  647.     fprintf(out,"static encode_aux_pigeonhole _vq_auxp_%s = {\n",name);
  648.     fprintf(out,"\t%g, %g, %d, %d,\n",
  649.         p->min,p->del,p->mapentries,p->quantvals);
  650.  
  651.     fprintf(out,"\t_vq_pigeonmap_%s,\n",name);
  652.  
  653.     fprintf(out,"\t%ld,\n",p->fittotal);
  654.     fprintf(out,"\t_vq_fitlist_%s,\n",name);
  655.     fprintf(out,"\t_vq_fitmap_%s,\n",name);
  656.     fprintf(out,"\t_vq_fitlength_%s\n};\n\n",name);
  657.   }
  658.  
  659.   if(n){
  660.     
  661.     /* ptr0 */
  662.     fprintf(out,"static long _vq_ptr0_%s[] = {\n",name);
  663.     for(j=0;j<n->aux;){
  664.       fprintf(out,"\t");
  665.       for(k=0;k<8 && j<n->aux;k++,j++)
  666.     fprintf(out,"%6ld,",n->ptr0[j]);
  667.       fprintf(out,"\n");
  668.     }
  669.     fprintf(out,"};\n\n");
  670.     
  671.     /* ptr1 */
  672.     fprintf(out,"static long _vq_ptr1_%s[] = {\n",name);
  673.     for(j=0;j<n->aux;){
  674.       fprintf(out,"\t");
  675.       for(k=0;k<8 && j<n->aux;k++,j++)
  676.     fprintf(out,"%6ld,",n->ptr1[j]);
  677.       fprintf(out,"\n");
  678.     }
  679.     fprintf(out,"};\n\n");
  680.     
  681.     /* p */
  682.     fprintf(out,"static long _vq_p_%s[] = {\n",name);
  683.     for(j=0;j<n->aux;){
  684.       fprintf(out,"\t");
  685.       for(k=0;k<8 && j<n->aux;k++,j++)
  686.     fprintf(out,"%6ld,",n->p[j]*c->dim);
  687.       fprintf(out,"\n");
  688.     }
  689.     fprintf(out,"};\n\n");
  690.     
  691.     /* q */
  692.     fprintf(out,"static long _vq_q_%s[] = {\n",name);
  693.     for(j=0;j<n->aux;){
  694.       fprintf(out,"\t");
  695.       for(k=0;k<8 && j<n->aux;k++,j++)
  696.     fprintf(out,"%6ld,",n->q[j]*c->dim);
  697.       fprintf(out,"\n");
  698.     }
  699.     fprintf(out,"};\n\n");
  700.   
  701.     fprintf(out,"static encode_aux_nearestmatch _vq_auxn_%s = {\n",name);
  702.     fprintf(out,"\t_vq_ptr0_%s,\n",name);
  703.     fprintf(out,"\t_vq_ptr1_%s,\n",name);
  704.     fprintf(out,"\t_vq_p_%s,\n",name);
  705.     fprintf(out,"\t_vq_q_%s,\n",name);
  706.     fprintf(out,"\t%ld, %ld\n};\n\n",n->aux,n->aux);
  707.   }
  708.  
  709.   /* tie it all together */
  710.   
  711.   fprintf(out,"static static_codebook %s = {\n",name);
  712.   
  713.   fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
  714.   fprintf(out,"\t_vq_lengthlist_%s,\n",name);
  715.   fprintf(out,"\t%d, %ld, %ld, %d, %d,\n",
  716.           c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep);
  717.   if(c->quantlist)
  718.     fprintf(out,"\t_vq_quantlist_%s,\n",name);
  719.   else
  720.     fprintf(out,"\tNULL,\n");
  721.  
  722.   if(n)
  723.     fprintf(out,"\t&_vq_auxn_%s,\n",name);
  724.   else
  725.     fprintf(out,"\tNULL,\n");
  726.   if(t)
  727.     fprintf(out,"\t&_vq_auxt_%s,\n",name);
  728.   else
  729.     fprintf(out,"\tNULL,\n");
  730.   if(p)
  731.     fprintf(out,"\t&_vq_auxp_%s,\n",name);
  732.   else
  733.     fprintf(out,"\tNULL,\n");
  734.  
  735.   fprintf(out,"\t0\n};\n\n");
  736.  
  737.   fprintf(out,"\n#endif\n");
  738. }
  739.